// Package loader provides on-demand loading functionality
package loader

import (
	"context"
	"fmt"
	"time"

	"github.com/smart-snapshotter/pkg/cache"
	"github.com/smart-snapshotter/pkg/storage"
)

// Loader represents an on-demand loader interface
type Loader interface {
	// Load loads data on demand
	Load(ctx context.Context, key string) ([]byte, error)

	// Prefetch prefetches related data
	Prefetch(ctx context.Context, keys []string) error

	// GetProgress returns loading progress
	GetProgress(ctx context.Context, key string) (Progress, error)

	// GetStats returns loader statistics
	GetStats(ctx context.Context) (Stats, error)
}

// Progress represents loading progress
type Progress struct {
	Key         string
	Status      string // "pending", "loading", "completed", "failed"
	BytesLoaded int64
	BytesTotal  int64
	StartTime   time.Time
	EndTime     time.Time
	Error       error
}

// Stats represents loader statistics
type Stats struct {
	TotalRequests    int64
	CacheHits        int64
	CacheMisses      int64
	PrefetchRequests int64
	ActiveDownloads  int64
	TotalBytesLoaded int64
	AverageLoadTime  time.Duration
}

// Config represents loader configuration
type Config struct {
	PrefetchEnabled bool
	PrefetchDepth   int
	MaxConcurrency  int
	Timeout         int64
}

// New creates a new loader
func New(config Config, storage storage.Backend, cache cache.Cache) (Loader, error) {
	return &SimpleLoader{
		config:  config,
		storage: storage,
		cache:   cache,
		stats:   Stats{},
	}, nil
}

// SimpleLoader implements a simple on-demand loader
type SimpleLoader struct {
	config  Config
	storage storage.Backend
	cache   cache.Cache
	stats   Stats
}

func (l *SimpleLoader) Load(ctx context.Context, key string) ([]byte, error) {
	// Try cache first
	if data, err := l.cache.Get(ctx, key); err == nil {
		l.stats.CacheHits++
		return data, nil
	}

	l.stats.CacheMisses++

	// Load from storage
	data, err := l.storage.LoadFile(ctx, key)
	if err != nil {
		return nil, fmt.Errorf("failed to load from storage: %w", err)
	}

	// Cache the result
	if err := l.cache.Set(ctx, key, data, time.Hour); err != nil {
		// Log error but don't fail the operation
		fmt.Printf("Warning: failed to cache data: %v\n", err)
	}

	l.stats.TotalBytesLoaded += int64(len(data))
	l.stats.TotalRequests++

	return data, nil
}

func (l *SimpleLoader) Prefetch(ctx context.Context, keys []string) error {
	l.stats.PrefetchRequests++

	for _, key := range keys {
		// Load each key
		if _, err := l.Load(ctx, key); err != nil {
			// Log error but continue with other keys
			fmt.Printf("Warning: failed to prefetch key %s: %v\n", key, err)
		}
	}

	return nil
}

func (l *SimpleLoader) GetProgress(ctx context.Context, key string) (Progress, error) {
	// For now, return dummy progress
	return Progress{
		Key:    key,
		Status: "completed",
	}, nil
}

func (l *SimpleLoader) GetStats(ctx context.Context) (Stats, error) {
	return l.stats, nil
}